﻿using ExcellentProjectPlus.Aplicacion.Calificaciones.Cursos;
using ExcellentProjectPlus.Dominio.Examenes.Entidades;
using ExcellentProjectPlus.Dominio.Examenes.Servicios.Calendarizaciones;
using ExcellentProjectPlus.Dominio.Seguridades.Entidades;
using ExcellentProjectPlus.Seguridades.Docentes;
using ExcellentProjectPlus.Seguridades.Estudiantes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;

namespace ExcellentProjectPlus.Aplicacion.Examenes.Calendarizaciones
{
    public class ServicioDeGestionDeCalendarizaciones
        : IServicioDeGestionDeCalendarizaciones
    {
        #region Propiedades
        IServicioDeAdministracionDeCalendarizacion _servicioDeAdministracionDeCalendarizaciones;
        IServicioDeGestionDeEstudiantes _servicioDeGestionDeEstudiantes;
        IServicioDeGestionDeCursos _servicioDeAdministracionDeCursos;
        #endregion

        #region Constructores
        public ServicioDeGestionDeCalendarizaciones(IServicioDeAdministracionDeCalendarizacion servicioDeAdministracionDeCalendarizaciones,
            IServicioDeGestionDeEstudiantes servicioDeGestionDeEstudiantes,
            IServicioDeGestionDeCursos servicioDeAdministracionDeCursos)
        {
            _servicioDeAdministracionDeCalendarizaciones = servicioDeAdministracionDeCalendarizaciones;
            _servicioDeGestionDeEstudiantes = servicioDeGestionDeEstudiantes;
            _servicioDeAdministracionDeCursos = servicioDeAdministracionDeCursos;
        }
        #endregion
        public IEnumerable<Calendarizacion> ObtenerCalendarizaciones()
        {
            IEnumerable<Calendarizacion> resultado = null;
            var trxOptions = new TransactionOptions();
            //Lectura con nivel de aislamiento ReadUncommited para evitar bloqueos en la base
            trxOptions.IsolationLevel = IsolationLevel.ReadUncommitted;
            trxOptions.Timeout = TimeSpan.FromMinutes(2);
            using (var transaccion = new TransactionScope(TransactionScopeOption.RequiresNew, trxOptions))
            {
                resultado = _servicioDeAdministracionDeCalendarizaciones.ObtenerCalendarizaciones();
                transaccion.Complete();
            }

            return resultado;
        }

        public Calendarizacion ObtenerCalendarizacionPorId(int id)
        {
            Calendarizacion resultado = null;
            var trxOptions = new TransactionOptions();
            //Lectura con nivel de aislamiento ReadUncommited para evitar bloqueos en la base
            trxOptions.IsolationLevel = IsolationLevel.ReadCommitted;
            trxOptions.Timeout = TimeSpan.FromMinutes(2);
            using (var transaccion = new TransactionScope(TransactionScopeOption.RequiresNew, trxOptions))
            {
                resultado = _servicioDeAdministracionDeCalendarizaciones.ObtenerCalendarizacionPorId(id);
                transaccion.Complete();
            }

            return resultado;
        }

        public void AgregarCalendarizacion(Calendarizacion calendarizacion)
        {
            _servicioDeAdministracionDeCalendarizaciones.AgregarCalendarizacion(calendarizacion);
        }

        public void ModificarCalendarizacion(Calendarizacion calendarizacion)
        {
            _servicioDeAdministracionDeCalendarizaciones.ModificarCalendarizacion(calendarizacion);
        }

        public void EliminarCalendarizacion(Calendarizacion calendarizacion)
        {
            _servicioDeAdministracionDeCalendarizaciones.EliminarCalendarizacion(calendarizacion);
        }


        public void Dispose()
        {
            throw new NotImplementedException();
        }


        public IEnumerable<Calendarizacion> ObtenerCalendarizacionesPaginado(int pagina, int tamanio)
        {
            return _servicioDeAdministracionDeCalendarizaciones.ObtenerCalendarizacionesPaginado(pagina, tamanio);
        }


        public IEnumerable<Calendarizacion> ObtenerFechasCalendarizacion(DateTime fechaseleccionada)
        {
            return _servicioDeAdministracionDeCalendarizaciones.ObtenerFechasCalendarizacion(fechaseleccionada);
        }


        public IEnumerable<InformacionCalendarizacionExamen> ObtenerInformacionCalendarizacionExamen(string estado)
        {
            return _servicioDeAdministracionDeCalendarizaciones.ObtenerInformacionCalendarizacionExamen(estado);
        }

        public IEnumerable<Calendarizacion> ObtenerExamenesPendientesPorCurso(int idCurso)
        {
            IEnumerable<Calendarizacion> resultado = null;
            var trxOptions = new TransactionOptions();
            //Lectura con nivel de aislamiento ReadUncommited para evitar bloqueos en la base
            trxOptions.IsolationLevel = IsolationLevel.ReadCommitted;
            trxOptions.Timeout = TimeSpan.FromMinutes(2);
            using (var transaccion = new TransactionScope(TransactionScopeOption.RequiresNew, trxOptions))
            {
                resultado = _servicioDeAdministracionDeCalendarizaciones.ObtenerExamenesPendientesPorCurso(idCurso);
                transaccion.Complete();
            }

            return resultado;
        }

        public IEnumerable<Calendarizacion> ObtenerExamenesPendientesPorEstudiante(int idEstudiante)
        {
            var estudiante = _servicioDeGestionDeEstudiantes.ObtenerEstudiantePorId(idEstudiante);
            if (estudiante == null)
                throw new ArgumentNullException("No se ha encontrado el estudiante");
            return _servicioDeAdministracionDeCalendarizaciones.ObtenerExamenesPendientesPorEstudiante(estudiante.IdCurso, idEstudiante);
        }


        public IEnumerable<InformacionCalendarizacionExamen> ObtenerInformacionCalendarizacionExamen(int idDocente, string estado)
        {
            IEnumerable<InformacionCalendarizacionExamen> resultado = null;
            var trxOptions = new TransactionOptions();
            //Lectura con nivel de aislamiento ReadUncommited para evitar bloqueos en la base
            trxOptions.IsolationLevel = IsolationLevel.ReadCommitted;
            trxOptions.Timeout = TimeSpan.FromMinutes(2);
            using (var transaccion = new TransactionScope(TransactionScopeOption.RequiresNew, trxOptions))
            {
                resultado = _servicioDeAdministracionDeCalendarizaciones.ObtenerInformacionCalendarizacionExamen(estado);
                transaccion.Complete();
            }

            return resultado;
        }

        public IEnumerable<Calendarizacion> ObtenerExamenesPendientesPorDocente(int idDocente)
        {
            List<Calendarizacion> resultado = new List<Calendarizacion>();
            var trxOptions = new TransactionOptions();
            //Lectura con nivel de aislamiento ReadUncommited para evitar bloqueos en la base
            trxOptions.IsolationLevel = IsolationLevel.ReadCommitted;
            trxOptions.Timeout = TimeSpan.FromMinutes(2);
            using (var transaccion = new TransactionScope(TransactionScopeOption.RequiresNew, trxOptions))
            {
                var cursosPorDocente = _servicioDeAdministracionDeCursos.ObtenerCursosPorDocente(idDocente).ToList();

                foreach (var curso in cursosPorDocente)
                {
                    resultado.AddRange(_servicioDeAdministracionDeCalendarizaciones.ObtenerExamenesPendientesPorCurso(curso.Id));
                }
                transaccion.Complete();
            }

            return resultado;
        }
    }
}